package com.lw.chat.protocol;

import com.lw.chat.message.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;

/**
 * 编解码器
 */
@Slf4j
public class MessageCodec extends ByteToMessageCodec<Message> {

    /**
     * 为了测试用的
     * @param ctx
     * @param msg
     * @param out
     * @throws Exception
     */
    public void encodePub4Test(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception{
        encode(ctx,msg,out);
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
        out.writeBytes(new byte[]{1,2,3,4});//魔数 4字节
        out.writeByte(1);//版本
        out.writeByte(0);// 序列化算法，0 jdk， 1 json
        out.writeByte(msg.getMessageType());//指令类型
        out.writeInt(msg.getSequenceId());//请求序号 4字节

        out.writeByte(0xff);//无意义，对齐填充用的，因为除去消息正文外，字节长度总值为15，为了凑2^n，所以加一个无意义的字节

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);//将对象转换为二进制的字节数组
        oos.writeObject(msg);
        byte[] bytes = bos.toByteArray();//对象字节数组

        out.writeInt(bytes.length);//正文长度 4字节
        out.writeBytes(bytes);//消息正文
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int magicNum = in.readInt();//魔数 4字节
        byte version = in.readByte();//版本
        byte serializerType = in.readByte();// 序列化算法，0 jdk， 1 json
        byte messageType = in.readByte();//指令类型
        int sequenceId = in.readInt();//请求序号 4字节

        //无意义的内容就读取忽略就行
        in.readByte();//无意义，对齐填充用的，因为除去消息正文外，字节长度总值为15，为了凑2^n，所以加一个无意义的字节

        int length = in.readInt();//正文长度 4字节

        byte[] bytes = new byte[length];
        in.readBytes(bytes,0,length);//消息正文

        //将字节数组反序列化为对象
        Message msg = null;
        if(serializerType==0){
            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bis);
            Object object = ois.readObject();
            if(object instanceof Message message){
                msg = message;
            }
        }
        out.add(msg);//为了将消息给下一个Handler使用

        log.debug("{},{},{},{},{},{}",magicNum,version,serializerType,messageType,sequenceId,length);
        log.debug("{}",msg);


    }
}
